home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-20 / rs0422.zip / LEVEL3 / BUFFER.C next >
C/C++ Source or Header  |  1990-01-30  |  10KB  |  391 lines

  1. /*
  2.  * Copyright 1988 by the Radio Amateur Telecommunications Society
  3.  * and Thomas A. Moulton, W2VY
  4.  *
  5.  * This software may only be modified, copied, distributed or
  6.  * executed for non-profit purposes by individuals operating
  7.  * systems in the Amateur Radio Service.  Credit to the
  8.  * author(s) and to the Radio Amateur Telecommunications Society
  9.  * must be made in modules where RATS provided software is used,
  10.  * and in any announcements and documentation.  
  11.  *
  12.  * As a non-profit, research and development organization,  the
  13.  * Radio Amateur Telecommunications Society distributes software
  14.  * in both executable and source forms.  This policy is in place
  15.  * to encourage the development and distribution of OSI-based,
  16.  * networking tools.  In order to protect the interests of the
  17.  * Society and the authors, we have placed some conditions
  18.  * of use on the software.  Other groups are encouraged
  19.  * to place the same or similar guidelines on
  20.  * software they produce.
  21.  *
  22.  * The Radio Amateur Telecommunications Society reserves the right
  23.  * to specify and alter the terms under which software provided by
  24.  * the Society may be used.  This policy is consistent with the 
  25.  * objective of uniform and consistent "Open Systems Interconnections."
  26.  * 
  27.  * All acceptable Amateur Radio related uses of this software
  28.  * will be outlined in the "ROSE Implementer's Guide".  Individuals
  29.  * or organizations wishing to add to, or modify the provisions of
  30.  * the guide to accommodate local or evolutionary requirements
  31.  * should document the proposed change(s) and forward them to the
  32.  * Society.  If accepted, written notification will be provided by
  33.  * the Society to the submitting organization or individual(s).
  34.  * The Society will then issue a "ROSE Implementer's Guide Change
  35.  * Notice".  Periodically, the Society will re-issue the "ROSE 
  36.  * Implementer's Guide" and incorporate the text of the change 
  37.  * notices.  This procedure has been put in to place to ensure
  38.  * compatibility between systems and to ensure their "Openness"
  39.  * and interoperability.
  40.  *
  41.  * No part of this software may be used in other packages 
  42.  * without prior authorization from the author or the Society.  
  43.  * Software incorporating this module, all or in part, must be 
  44.  * provided to the Society prior to distribution or use by
  45.  * anyone not directly involved in testing of the revised  
  46.  * environment.  Current releases of the combined software must
  47.  * be provided to the Society in both source and executable
  48.  * forms.  Adequate documention to produce an executable module 
  49.  * from the provided source must also be included.
  50.  *
  51.  * Non-Amateur Radio non-profit uses may be authorized on a case
  52.  * by case basis.  Inquiries for such use may be made in writing
  53.  * to the Society. Non-commercial uses consistent with the
  54.  * general principles of Open Systems Interconnection Reference
  55.  * Model will be generally considered with favor.
  56.  *
  57.  * Commercial licensing of the software is also available based
  58.  * on normal commercial terms.  Licensing inquiries should be
  59.  * directed to the Society.  Commercial licensing of the standard
  60.  * software will be done in situations which materially benefit
  61.  * the Amateur Radio Packet Network.  Additional licensing is
  62.  * reserved by the individual authors.
  63.  * 
  64.  * The Radio Amateur Telecommunications Society provides this software
  65.  * on an "as is" basis.  The Society assumes no liability for
  66.  * loss incurred through the use of this software.  Amateur Radio
  67.  * use of this software implies non-commercial and voluntary 
  68.  * development, deployment and use of this software in a "Amateur",
  69.  * non-commercial service.  Commercial users are encouraged to
  70.  * inspect their copies of the source code.  Source code modification
  71.  * licenses are available if a combined Object and Source Code
  72.  * license was not originally established.
  73.  * 
  74.  * The Society may be contacted by writing or calling at:
  75.  * 
  76.  * The Radio Amateur Telecommunications Society 
  77.  * 206 North Vivyen Street.
  78.  * Bergenfield, New Jersey 07621
  79.  *
  80.  * Telephone: 201-387-8896
  81.  *
  82.  */
  83. /* buffer.c */
  84.  
  85. /* This file contains the buffer access routines
  86.  
  87.     Buffer get next char
  88.     bgetch(datastr) : integer, char or -1 if EOF
  89.  
  90.     Buffer append ch
  91.     bappch(datastr,ch)
  92.  
  93.     buflen(datastr)        Return length of packet
  94.  
  95.     binsert(datastr1, datastr2)    Insert buf1 before buf2
  96.  
  97.     dup_pkt(datastr) : datastr    dup buffer headers, same data
  98.  
  99. */
  100. #define buftst 0
  101. #if buftst
  102. #define BUFCHK(a) buf_chk(a)
  103. #else
  104. #define BUFCHK
  105. #endif
  106.  
  107. /* This is also in assembly in LEVEL1.AS, the C version is being used now */
  108. int bgetch(b)
  109. struct datastr **b;
  110. {
  111.     register struct datastr *b1;
  112.     struct datastr *b2;    /* Needs to be re-entrant */
  113.  
  114.     if ((b1 = *b) == (struct datastr *)NULL) return EOF;
  115.     while ( (b1->rdata == b1->wdata) /* This segment is empty, try next */
  116.         || (b1->rdata > b1->max) ) /* Hit eof for this one */ {
  117.         b2 = b1;
  118.         b1 = b1->nexts;            /* Get next segment */
  119.         free(b2);            /* Free old */
  120.         if (b1 == (struct datastr *)NULL) /* Hit EOF, no data */ {
  121.             *b=(struct datastr *)NULL;
  122.             return EOF;
  123.         }
  124.     }
  125.     *b=b1;
  126.     return ((int)*b1->rdata++);
  127. }
  128.  
  129. int bappch(b, ch)
  130. register struct datastr *b;
  131. unsigned char ch;    /* Needs to be re-entrant */
  132. {
  133.     while (b->nexts) b=b->nexts;
  134.     if (b->wdata > b->max) return EOF;
  135.     *b->wdata++ = ch;
  136.     if (b->wdata > b->max) return 1;
  137.     return 0;
  138. }
  139.  
  140. int buflen(b1)
  141. register struct datastr *b1;
  142. {
  143.     static int cnt;
  144.  
  145.     cnt=0;
  146.     BUFCHK(b1);
  147.     while (b1 != (struct datastr *)NULL) {
  148.         cnt += (b1->wdata - b1->rdata);
  149.         b1 = b1->nexts;
  150.     }
  151.     return cnt;
  152. }
  153.  
  154. struct datastr *
  155. binsert(b1,b2)
  156. struct datastr *b1, *b2;
  157. {
  158.     static struct datastr *bo, *bn;
  159.     register struct datastr *b;
  160.  
  161.     bo=b2;        /* Old root of the packet */
  162.     b=bn=b1;    /* New root, ie. bufs to insert */
  163.     BUFCHK(bo);
  164.     BUFCHK(bn);
  165.     if (bo == (struct datastr *)NULL) return bn;
  166.     if (bn == (struct datastr *)NULL) return bo;
  167.     while (b->nexts != NULL) b= b->nexts;
  168.     b->nexts=bo;
  169.     bo->next=NULL;
  170.     return bn;
  171. }
  172.  
  173. #if 0
  174. struct datastr *
  175. dup_pkt(b)
  176. register struct datastr *b;
  177. {
  178.     static struct datastr *p1;
  179.     static unsigned char *c;
  180.  
  181.     if (b == (struct datastr *)NULL) return b;
  182.  
  183.     if ((p1=new_buffer(buflen(b))) == NULL) return p1;
  184.     do {
  185.         for (c=b->rdata;c<b->wdata;c++) bappch(p1,*c);
  186.         b=b->nexts;
  187.     } while (b);
  188.     return p1;
  189. }
  190. #else
  191. struct datastr *
  192. dup_pkt(b1)
  193. struct datastr *b1;
  194. {
  195.     static struct datastr *pkt, *p, *b;
  196.     register struct datastr *p1;
  197.  
  198.     b=b1;
  199.     BUFCHK(b);
  200.     pkt=new_buffer(0);
  201.     if (pkt == (struct datastr *)NULL) return NULL;
  202. /*    pkt->next=pkt->nexts=NULL; Done in New_buffer() */
  203.     pkt->rdata = b->rdata;
  204.     pkt->wdata = b->wdata;
  205.     pkt->max = b->max;
  206.     p=pkt;
  207.     while (b != (struct datastr *)NULL) {
  208.         if (b=b->nexts) /* Copy pointers */ {
  209.             p1=new_buffer(0);
  210.             if (p1 == (struct datastr *)NULL) /* No memory, free pkt and fail */ {
  211.                 free_pkt(pkt);
  212.                 return (struct datastr *)NULL;
  213.             }
  214.             p->nexts=p1;
  215.             p1->rdata=b->rdata;
  216.             p1->wdata=b->wdata;
  217.             p1->max = b->max;
  218.             p=p1;
  219.         }
  220.     }
  221.     return pkt;
  222. }
  223. #endif
  224.  
  225. void
  226. free_pktx(p)
  227. struct datastr **p;
  228. {
  229.     register struct datastr *b;
  230.  
  231.     if (p) {
  232.         if (b = *p) {
  233.             free_pktx(&b->nexts);
  234.             free(b);
  235.             *p = NULL;
  236.         }
  237.     }
  238. }
  239.  
  240. free_queue(q)
  241. struct datastr **q;
  242. {
  243.     register struct datastr *b;
  244.  
  245.     if (q) {
  246.         if (b = *q) {
  247.             free_queue(&b->next);
  248.             free_pktx(q);
  249.         }
  250.     }
  251. }
  252.  
  253. #if 0
  254. struct datastr *
  255. frag_pkt(px,size)    /* returns a NULL terminated queue of packets */
  256. struct datastr *px;
  257. int size;
  258. {
  259.     static struct datastr *p, *p1, *p2, *pr;
  260.     static int i;
  261.  
  262.     p=px;
  263.     p->next=NULL;
  264.     if (buflen(p) <= size) return p;
  265.     pr=p;
  266.     p1=NULL;
  267.     while (buflen(p) > size) {
  268.         if ((p2=new_buffer(size)) == NULL) break;
  269.         for (i=0;i<size;i++) bappch(p2,bgetch(&p));
  270.         if (!p1) pr=p2;
  271.         if (p1) p1->next=p2;
  272.         p1=p2;
  273.     }
  274.     if (p && p1) p1->next=p;
  275.     return pr;
  276. }
  277. #else
  278.  
  279. struct datastr *
  280. frag_pkt(px,siz)    /* returns a NULL terminated queue of packets */
  281. struct datastr *px;
  282. int siz;
  283. {
  284.     static struct datastr *p, *pk, *pks;
  285.     register struct datastr *pkr;
  286.     static int size, len, i;
  287.  
  288.     pkr=px;
  289.     pkr->next=NULL;
  290.     BUFCHK(pkr);
  291.     size=siz;
  292.     if (buflen(pkr) <= size) return pkr;
  293.     len=0;
  294.     p=pk=pks=NULL;
  295.     while (pkr) /* There is more to process */ {
  296.         i=pkr->wdata - pkr->rdata;
  297.         puthex2("frag",len,"",i);
  298.         if (i+len <= size) /* Move the segment over */ {
  299.             if (!pks) /* Start of packet */ {
  300.                 if (pk) pk->next=pkr;
  301.                 pk=pkr;
  302.                 if (!p) p=pkr;    /* Return value, first packet */
  303.             }
  304.             else /* Just add to end of segment queue */ {
  305.                 pks->nexts=pkr;
  306.             }
  307.             pks=pkr;    /* Current Seg */
  308.             pkr=pkr->nexts;    /* Advance to next seg */
  309.             pks->nexts=NULL;
  310.             len += i;
  311.         }
  312.         else /* Split Segment */ {
  313.             if (!pks) /* Start of a packet */ {
  314.                 pks=new_buffer(0);
  315.                 if (pk) pk->next=pks;
  316.                 pk=pks;
  317.                 if (!p) p=pk;
  318.             }
  319.             else {
  320.                 pks->nexts=new_buffer(0);
  321.                 pks=pks->nexts;
  322.             }
  323.             pks->rdata=pkr->rdata;
  324.             pks->wdata=pkr->rdata + size-len;
  325.             pks->max=pks->wdata -1;
  326.             pkr->rdata += size-len;
  327.             len=size;
  328.         }
  329.         if (len == size) {
  330.             pks=NULL;    /* Start a new packet */
  331.             len=0;
  332.         }
  333.     }
  334.     BUFCHK(p);
  335.     return p;
  336. }
  337. #endif
  338.  
  339. struct datastr *
  340. mkpkt(s)
  341. register char *s;
  342. {
  343.     static struct datastr *p;
  344.     int strlen();
  345.  
  346.     p=new_buffer(strlen(s)+30);    /* Room for message and some spare */
  347.     if (p) while (*s) bappch(p,(*s++));
  348.     BUFCHK(p);
  349.     return p;
  350. }
  351.  
  352. #if buftst
  353. int is_ROM(i)
  354. int i;
  355. {
  356.     return (i>0);
  357. }
  358.  
  359. buf_chk(p)
  360. struct datastr *p;
  361. {
  362.     struct datastr *p1;
  363.  
  364.     while (p) {
  365.         if (is_ROM(p) || is_ROM(p->nexts) || is_ROM(p->next) ||
  366.             !p->rdata || !p->wdata || !p->max) restart();
  367.         p1=p->nexts;
  368.         while (p1) {
  369.             if (is_ROM(p1) ||!p->rdata || !p->wdata
  370.                 || !p->max) restart();
  371.             p1=p1->nexts;
  372.         }
  373.         p=p->next;
  374.     }
  375. }
  376. #endif
  377.  
  378. struct datastr *
  379. bappstr(bp, str)
  380. struct datastr *bp;
  381. register char *str;
  382. {
  383.     if (bp) {
  384.         while (*str) {
  385.             if (bappch(bp, *str) != -1) str++;
  386.             else return (binsert(bp,mkpkt(str)));
  387.         }
  388.     }
  389.     return bp;
  390. }
  391.